//
//  BlockModel.h
//  ReviewDemo
//
//  Created by 龙 on 2018/3/24.
//  Copyright © 2018年 long. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface BlockModel : NSObject
- (void)testMethod;
@end

/*
 
 https://blog.csdn.net/puyangdev/article/details/68064841?winzoom=1
  clang -rewrite-objc 深入研究
 
 Blocks 的研究 （研究内存后回头再次研究）
 Blocks，带有自动变量（局部变量）的匿名函数。
 Block在OC中的实现如下：
 
 struct Block_layout {
 void *isa;
 int flags;
 int reserved;
 void (*invoke)(void *, ...);
 struct Block_descriptor *descriptor;
 //Imported variables.
};

struct Block_descriptor {
    unsigned long int reserved;
    unsigned long int size;
    void (*copy)(void *dst, void *src);
    void (*dispose)(void *);
};

 从结构图中很容易看到isa，所以OC处理Block是按照对象来处理的.在iOS中，isa常见的就是
  _NSConcreteStackBlock，//堆
  _NSConcreteMallocBlock，
  _NSConcreteGlobalBlock这3种 //全局的
 
 目录
 一.Block捕获外部变量实质
 二.Block的copy和release
 三.Block中__block实现原理
 
 
 一、外部变量：
     自动变量
     静态变量
     静态全局变量
     全局
 
     问题一、为什么在Block里面不加__bolck不允许更改变量？
     问题二、为什么自动变量的值没有增加，而其他几个变量的值是增加的？自动变量是什么状态下被block捕获进去的？

     自动变量是以值传递方式传递到Block的构造函数里面去的。Block只捕获Block中会用到的变量。
     由于只捕获了自动变量的值，并非内存地址，所以Block内部不能改变自动变量的值。
     Block捕获的外部变量可以改变值的是静态变量，静态全局变量，全局变量。
     Block中改变变量值有2种方式，一是传递内存地址指针到Block中，二是改变存储区方式(__block)。
 
 二、Block的copy和release
    1、OC中，一般Block就分为以下3种：_NSConcreteStackBlock，_NSConcreteMallocBlock，_NSConcreteGlobalBlock。先来说明一下3者的区别。
    （1）、从捕获外部变量的角度上来看：
     _NSConcreteStackBlock：只用到外部局部变量、成员属性变量，且没有强指针引用的block都是StackBlock。
        StackBlock的生命周期由系统控制的，一旦返回之后，就被系统销毁了。
     _NSConcreteMallocBlock：有强指针引用或copy修饰的成员属性引用的block会被复制一份到堆中成为MallocBlock，没有强指针引用即销毁，生命周期由程序员控制
     _NSConcreteGlobalBlock：没有用到外界变量或只用到全局变量、静态变量的block为GlobalBlock，生命周期从创建到应用程序结束。

     （2）、从持有对象的角度上来看：（retainCount 值得改变）
      _NSConcreteStackBlock是不持有对象的。
      _NSConcreteMallocBlock是持有对象的。
      _NSConcreteGlobalBlock也不持有对象
 

 */
